<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>手写 Promise-ES6-V2</h1>
    <script>
      /**
       * 手写 Promise   功能不全  简洁版
       */
      const PENDING = "pending";
      const FULLED = "fulleding";
      const FAILED = "faileding";

      class MyPromise {
        #status = PENDING;
        #result = undefined;
        queue = [];
        constructor(exetrace) {
          const reslove = (result) => {
            this.#changeStatus(FULLED, result);
          };
          const reject = (error) => {
            this.#changeStatus(FAILED, error);
          };

          try {
            exetrace(reslove, reject);
          } catch (err) {
            reject(err);
          }
        }

        #changeStatus(status, result) {
          if (this.#status !== PENDING) return;
          this.#status = status;
          this.#result = result;
          this.#run();
        }

        #handlerCallback(callback, reslove, reject) {
          // 先判断下是否是函数，不是直接透出
          if (typeof callback !== "function") {
            queueMicrotask(() => {
              const soted = this.#status === FULLED ? reslove : reject;
              soted(this.#result);
            });
          } else {
            queueMicrotask(() => {
              try {
                const data = callback(this.#result);
                reslove(data);
              } catch (err) {
                reject(err);
              }
            });
          }
        }

        // 运行
        #run() {
          if (this.#status === PENDING) return;
          while (this.queue.length) {
            const { onSuccessCb, onFailedCb, reslove, reject } =
              this.queue.shift();
            if (this.#status === FULLED) {
              this.#handlerCallback(onSuccessCb, reslove, reject);
            } else {
              this.#handlerCallback(onFailedCb, reslove, reject);
            }
          }
        }

        then(onSuccessCb, onFailedCb) {
          return new MyPromise((reslove, reject) => {
            this.queue.push({
              onSuccessCb,
              onFailedCb,
              reslove,
              reject,
            });
            this.#run();
          });
        }

        catch(onFailedCb) {
          return this.then(undefined, onFailedCb);
        }
      }

      const p = new MyPromise((reslove, reject) => {
        // reject(11); // 如果没有 catch，也不会报错，TODO
        reslove(11);
      });
      p.then((ret) => {
        return ret + 1;
      }).then((ret) => {
        console.log(ret);
      });

      // const p2 = new Promise((reslove, reject) => {
      //   reject(111);
      // });

      // p2.then((ret) => {
      //   return ret;
      // }).catch((e) => {
      //   console.log(e);
      // });
    </script>
  </body>
</html>
